#pragma once
#include "../Util/util.hpp"
#include <mutex>
#include <assert.h>
#include <stdlib.h>

class user_table
{
public:
    user_table(const std::string& host, const std::string& user, const std::string& passwd,
        const std::string& db, int port)
    {
        _mysql = Mysql_Util::mysql_create(host.c_str(),user.c_str(),passwd.c_str(),db.c_str(),port);
        assert(_mysql != NULL);
    }
    ~user_table()
    {
        Mysql_Util::mysql_des(_mysql);
        _mysql == NULL;
    }

    // 注册-添加用户
    bool insert(Json::Value &user)
    {
#define INSERT_USER "insert into user values(NULL, '%s', '%s', 1000, 0, 0);"
        char sql[4096] = {0};
        sprintf(sql, INSERT_USER, user["username"].asCString(), user["password"].asCString());
        bool ret = Mysql_Util::mysql_exe(_mysql, sql);
        if(ret == false)
        {
            LOG(ERROR) << "注册失败..." << "\n";
            return false;
        }
        LOG(INFO) << "注册成功..." << "\n";
        return true;
    }
    // 登录并获取用户信息
    bool login(Json::Value &user)
    {
#define LOGIN_USER "select id, score, total_count, win_count from user where username='%s' and password='%s';"
        if(user["username"].isNull() || user["password"].isNull())
        {
            LOG("ERROR") << "请输入用户名或密码" << "\n";
            return false; 
        }
        char sql[4096] = {0};
        sprintf(sql, LOGIN_USER, user["username"].asCString(), user["password"].asCString());
        MYSQL_RES* res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = Mysql_Util::mysql_exe(_mysql, sql);
            if(ret == false)
            {
                LOG(ERROR) << "登录失败..." << "\n";
                return false;
            }
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                LOG(ERROR) << "保存本地失败.." << "\n";
                return false;
            }
        }
        int num_row = mysql_num_rows(res);
        if(num_row != 1)
        {
            LOG(ERROR) << "数据不唯一.." << "\n";
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::Int64)std::stol(row[0]);
        user["score"] = (Json::Int64)std::stol(row[1]);
        user["total_count"] = (Json::Int64)std::stol(row[2]);
        user["win_count"] = (Json::Int64)std::stol(row[3]);
        LOG(INFO) << "登录成功..." << "\n";
        return true;
    }
    // 通过用户名获取用户信息
    bool sel_by_name(const std::string& name, Json::Value &user)
    {
#define GET_BY_NAME "select id, score, total_count, win_count from user where username='%s';"
        char sql[4096] = {0};
        sprintf(sql, GET_BY_NAME, name.c_str());
        MYSQL_RES* res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = Mysql_Util::mysql_exe(_mysql, sql);
            if(ret == false)
            {
                LOG(ERROR) << "通过用户名获取用户信息失败..." << "\n";
                return false;
            }
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                LOG(ERROR) << "保存本地失败.." << "\n";
                return false;
            }
        }
        int num_row = mysql_num_rows(res);
        if(num_row != 1)
        {
            LOG(ERROR) << "数据不唯一.." << "\n";
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::Int64)std::stol(row[0]);
        user["username"] = name;
        user["score"] = (Json::Int64)std::stol(row[1]);
        user["total_count"] = (Json::Int64)std::stol(row[2]);
        user["win_count"] = (Json::Int64)std::stol(row[3]);
        return true;
    }
    // 通过id获取用户信息
    bool sel_by_id(uint64_t id, Json::Value &user)
    {
        #define GET_BY_ID "select username, score, total_count, win_count from user where id='%lu';"
        char sql[4096] = {0};
        sprintf(sql, GET_BY_ID, id);
        MYSQL_RES* res = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            bool ret = Mysql_Util::mysql_exe(_mysql, sql);
            if(ret == false)
            {
                LOG(ERROR) << "通过id获取用户信息失败..." << "\n";
                return false;
            }
            res = mysql_store_result(_mysql);
            if(res == NULL)
            {
                LOG(ERROR) << "保存本地失败.." << "\n";
                return false;
            }
        }
        int num_row = mysql_num_rows(res);
        if(num_row != 1)
        {
            LOG(ERROR) << "数据不唯一.." << "\n";
            return false;
        }
        MYSQL_ROW row = mysql_fetch_row(res);
        user["id"] = (Json::Int64)id;
        user["username"] = row[0];// 这个是字符串！
        user["score"] = (Json::Int64)std::stol(row[1]);
        user["total_count"] = (Json::Int64)std::stol(row[2]);
        user["win_count"] = (Json::Int64)std::stol(row[3]);
        return true;
    }
    // 赢-》积分+30，总场次+1，胜利场次+1
    bool win(uint64_t id)
    {
#define WIN_USER "update user set score=score+30, total_count=total_count+1,win_count=win_count+1 where id='%lu';"
        char sql[4096] = {0};
        sprintf(sql, WIN_USER, id);
        bool ret = Mysql_Util::mysql_exe(_mysql, sql);
        if(ret == false)
        {
            LOG(ERROR) << "win用户信息修改失败..." << "\n";
            return false;
        }
        return true;
    }
    // 输-》积分-30，总场次+1，其他不变
    bool lose(uint64_t id)
    {
#define LOSE_USER "update user set score=score-30, total_count=total_count+1 where id='%lu';"
        char sql[4096] = {0};
        sprintf(sql, LOSE_USER, id);
        bool ret = Mysql_Util::mysql_exe(_mysql, sql);
        if(ret == false)
        {
            LOG(ERROR) << "lose用户信息修改失败..." << "\n";
            return false;
        }
        return true;
    }

private:
    MYSQL *_mysql;
    std::mutex _mutex;
};
